<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Azul CSS Reftest Results</title>
  <style>
    /* Variables */
    :root {
      /* Light mode colors (default) */
      --color-primary: #4a6bdf;
      --color-primary-light: #6f89e6;
      --color-secondary: #2ecc71;
      --color-warning: #f39c12;
      --color-danger: #e74c3c;
      --color-dark: #34495e;
      --color-light: #f5f7fa;
      --color-gray: #95a5a6;
      --font-main: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
      --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
      --border-radius: 8px;
      --shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
      
      /* Background and text colors */
      --bg-main: var(--color-light);
      --text-main: var(--color-dark);
      --bg-card: white;
      --bg-button: white;
      --bg-button-hover: var(--color-light);
      --bg-overlay: rgba(0, 0, 0, 0.75);
      --bg-code: #f8f9fa;
      
      /* Borders and shadows */
      --border-color: #eee;
      --border-color-light: #e0e0e0;
      --shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
      --shadow-hover: 0 8px 20px rgba(0, 0, 0, 0.1);
      --backdrop-blur: blur(3px);
    }

    /* Reset and base styles */
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body { 
      font-family: var(--font-main); 
      line-height: 1.6;
      color: var(--text-main);
      background-color: var(--bg-main);
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 2rem 1rem;
    }

    h1, h2, h3 {
      color: var(--text-main);
      margin-bottom: 1rem;
    }

    h1 {
      font-size: 2rem;
      border-bottom: 3px solid var(--color-primary);
      padding-bottom: 0.5rem;
      margin-bottom: 2rem;
      display: inline-block;
    }

    h2 {
      font-size: 1.5rem;
    }

    h3 {
      font-size: 1.2rem;
    }

    /* Summary section */
    .summary {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
      gap: 0.75rem;
      margin-bottom: 1.5rem;
    }

    .summary-box {
      background-color: var(--bg-card);
      border-radius: var(--border-radius);
      padding: 1rem;
      text-align: center;
      box-shadow: var(--shadow);
      transition: transform 0.2s;
    }

    .summary-box:hover {
      transform: translateY(-3px);
    }

    .summary-box.total {
      border-top: 4px solid var(--color-primary);
    }

    .summary-box.passed {
      border-top: 4px solid var(--color-secondary);
    }

    .summary-box.failed {
      border-top: 4px solid var(--color-danger);
    }

    .summary-number {
      font-size: 2.5rem;
      font-weight: 700;
      margin-bottom: 0.5rem;
    }

    .summary-label {
      font-size: 1rem;
      color: var(--color-gray);
    }

    /* Controls */
    .controls {
      display: flex;
      flex-wrap: wrap;
      gap: 1rem;
      margin-bottom: 2rem;
      justify-content: space-between;
      align-items: center;
    }

    .search-controls {
      flex: 1;
      min-width: 250px;
      max-width: 500px;
    }

    .search-input {
      width: 100%;
      padding: 0.75rem 1rem;
      font-size: 0.95rem;
      border: 1px solid var(--border-color-light);
      border-radius: var(--border-radius);
      background-color: var(--bg-card);
      color: var(--text-main);
      font-family: var(--font-main);
    }

    .search-input:focus {
      outline: 2px solid var(--color-primary);
      outline-offset: 0px;
    }

    .sort-controls {
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem;
    }

    .button {
      padding: 0.75rem 1rem;
      background-color: var(--bg-button);
      border: 1px solid var(--border-color-light);
      border-radius: var(--border-radius);
      cursor: pointer;
      font-size: 0.9rem;
      transition: all 0.2s;
      box-shadow: var(--shadow);
    }

    .button:hover {
      background-color: var(--bg-button-hover);
    }

    .button.active {
      background-color: var(--color-primary);
      color: white;
      border-color: var(--color-primary);
    }

    .filter-controls {
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem;
    }

    .filter-button.pass {
      border-left: 4px solid var(--color-secondary);
    }

    .filter-button.warning {
      border-left: 4px solid var(--color-warning);
    }

    .filter-button.fail {
      border-left: 4px solid var(--color-danger);
    }

    /* Test grid */
    .test-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: 1rem;
    }

    .category-header {
      font-size: 1.5rem;
      font-weight: 600;
      color: var(--color-primary);
      margin-top: 1.5rem;
      margin-bottom: 0.75rem;
      padding-bottom: 0.5rem;
      border-bottom: 2px solid var(--color-primary);
      grid-column: 1 / -1;
    }

    .category-header:first-child {
      margin-top: 0;
    }

    .test-card {
      background-color: var(--bg-card);
      border-radius: var(--border-radius);
      overflow: hidden;
      box-shadow: var(--shadow);
      transition: transform 0.2s, box-shadow 0.2s;
    }

    .test-card:hover {
      transform: translateY(-3px);
      box-shadow: var(--shadow-hover);
    }

    .test-card.pass {
      border-left: 5px solid var(--color-secondary);
      background-color: rgba(46, 204, 113, 0.05);
    }

    .test-card.warning {
      border-left: 5px solid var(--color-warning);
      background-color: rgba(243, 156, 18, 0.05);
    }

    .test-card.fail {
      border-left: 5px solid var(--color-danger);
      background-color: rgba(231, 76, 60, 0.05);
    }

    .test-header {
      padding: 1rem;
      display: flex;
      justify-content: space-between;
      align-items: center;
      cursor: pointer;
      user-select: none;
    }

    .test-header:hover {
      background-color: var(--bg-button-hover);
    }

    .test-header-left {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      flex: 1;
    }

    .collapse-icon {
      font-size: 1.2rem;
      transition: transform 0.2s;
      min-width: 24px;
    }

    .test-card.collapsed .collapse-icon {
      transform: rotate(-90deg);
    }

    .test-card.collapsed .test-body {
      display: none;
    }

    .test-title {
      margin: 0;
      font-weight: 600;
    }

    .test-result {
      padding: 0.25rem 0.75rem;
      border-radius: 999px;
      font-size: 0.8rem;
      font-weight: 600;
    }

    .test-result.pass {
      background-color: var(--color-secondary);
      color: white;
    }

    .test-result.warning {
      background-color: var(--color-warning);
      color: white;
    }

    .test-result.fail {
      background-color: var(--color-danger);
      color: white;
    }

    .test-metadata {
      padding: 1rem;
      border-bottom: 1px solid var(--border-color);
    }

    .test-title-full {
      font-weight: 600;
      margin-bottom: 0.5rem;
    }

    .test-assert {
      font-style: italic;
      color: var(--color-gray);
      font-size: 0.9rem;
      margin-bottom: 0.5rem;
    }

    .test-link {
      font-size: 0.8rem;
      color: var(--color-primary);
      text-decoration: none;
    }

    .test-link:hover {
      text-decoration: underline;
    }

    .test-content {
      display: grid;
      grid-template-columns: 1fr;
      border-bottom: 1px solid var(--border-color);
    }

    .test-image-container {
      padding: 1rem;
      text-align: center;
    }

    .test-image {
      max-width: 100%;
      height: auto;
      border: 1px solid var(--border-color);
      border-radius: var(--border-radius);
    }

    .test-image-label {
      margin-top: 0.5rem;
      font-size: 0.8rem;
      color: var(--color-gray);
    }

    .test-data-buttons {
      padding: 1rem;
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem;
    }

    .data-button {
      flex: 1;
      min-width: 100px;
      padding: 0.5rem;
      background-color: var(--bg-code);
      border: 1px solid var(--border-color-light);
      border-radius: var(--border-radius);
      cursor: pointer;
      font-size: 0.9rem;
      text-align: center;
      transition: all 0.2s;
    }

    .data-button:hover {
      background-color: var(--color-primary-light);
      color: white;
    }

    /* Overlay */
    .overlay {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: var(--bg-overlay);
      z-index: 1000;
      overflow-y: auto;
      backdrop-filter: var(--backdrop-blur);
    }

    .overlay-content {
      background-color: var(--bg-card);
      margin: 2rem auto;
      padding: 1.5rem;
      max-width: 95%;
      width: 1000px;
      border-radius: var(--border-radius);
      position: relative;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    }

    .overlay-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 1rem;
      padding-bottom: 0.5rem;
      border-bottom: 1px solid var(--border-color);
    }

    .overlay-title {
      margin: 0;
      font-size: 1.5rem;
    }

    .overlay-close {
      font-size: 1.5rem;
      cursor: pointer;
      width: 32px;
      height: 32px;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 50%;
      transition: all 0.2s;
    }

    .overlay-close:hover {
      background-color: var(--bg-button-hover);
    }

    .overlay-data {
      margin-top: 1rem;
      max-height: 70vh;
      overflow: auto;
      background-color: var(--bg-code);
      padding: 1rem;
      border-radius: var(--border-radius);
      font-family: var(--font-mono);
      font-size: 0.9rem;
      white-space: pre-wrap;
      line-height: 1.4;
    }

    /* Empty state */
    .empty-state {
      text-align: center;
      padding: 3rem 1rem;
      color: var(--color-gray);
    }

    .empty-icon {
      font-size: 3rem;
      margin-bottom: 1rem;
    }

    /* No test matches filter */
    .no-results {
      display: none;
      text-align: center;
      padding: 2rem;
      color: var(--color-gray);
      background-color: var(--bg-card);
      border-radius: var(--border-radius);
      box-shadow: var(--shadow);
    }

    /* Header styles */
    .report-header {
      background-color: var(--bg-card);
      border-radius: var(--border-radius);
      padding: 1rem;
      margin-bottom: 1.5rem;
      box-shadow: var(--shadow);
    }

    .header-metadata {
      display: flex;
      flex-wrap: wrap;
      gap: 1rem;
      align-items: center;
    }

    .metadata-item {
      flex: 1;
      min-width: 200px;
    }

    .metadata-item p {
      margin: 0.25rem 0;
      font-size: 0.9rem;
    }

    .metadata-item.error {
      color: var(--color-danger);
    }

    .metadata-item.success {
      color: var(--color-secondary);
    }

    .project-info {
      margin-top: 0.5rem;
    }

    .links {
      font-weight: 500;
      font-size: 0.9rem;
    }

    .links a {
      color: var(--color-primary);
      text-decoration: none;
    }

    .links a:hover {
      text-decoration: underline;
    }

    code {
      font-family: var(--font-mono);
      background-color: var(--bg-code);
      padding: 0.1rem 0.3rem;
      border-radius: 3px;
      font-size: 0.9em;
    }

    /* Media queries */
    @media (min-width: 768px) {
      .test-content {
        grid-template-columns: repeat(2, 1fr);
      }
    }

    @media (min-width: 1024px) {
      .test-grid {
        grid-template-columns: repeat(auto-fill, minmax(600px, 1fr));
      }
    }

    @media (max-width: 767px) {
      .controls {
        flex-direction: column;
        align-items: stretch;
      }
      
      .sort-controls, .filter-controls {
        justify-content: center;
      }
      
      .test-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
      }
      
      .test-result {
        align-self: flex-start;
      }
    }

    /* Dark mode styles */
    @media (prefers-color-scheme: dark) {
      :root {
        /* Override colors for dark mode */
        --color-dark: #f5f7fa;
        --color-light: #2c3e50;
        
        /* Background and text colors */
        --bg-main: #1a1a1a;
        --text-main: #f5f7fa;
        --bg-card: #2c3e50;
        --bg-button: #34495e;
        --bg-button-hover: #3d5a76;
        --bg-overlay: rgba(0, 0, 0, 0.85);
        --bg-code: #2d3748;
        
        /* Borders and shadows */
        --border-color: #3d5a76;
        --border-color-light: #3d5a76;
        --shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
        --shadow-hover: 0 8px 20px rgba(0, 0, 0, 0.3);
      }
      
      /* Override specific elements */
      body {
        color: var(--text-main);
        background-color: var(--bg-main);
      }
      
      .container {
        background-color: var(--bg-main);
      }
      
      .summary-box, .test-card, .button, .no-results, .report-header, .overlay-content {
        background-color: var(--bg-card);
        color: var(--text-main);
      }
      
      .button {
        background-color: var(--bg-button);
        border-color: var(--border-color-light);
      }
      
      .button:hover {
        background-color: var(--bg-button-hover);
      }
      
      .test-header, .test-metadata, .overlay-header {
        border-color: var(--border-color);
      }
      
      .test-content {
        border-color: var(--border-color);
      }
      
      .test-image {
        border-color: var(--border-color);
      }
      
      .test-image-label, .summary-label, .test-assert {
        color: var(--color-gray);
      }
      
      .data-button {
        background-color: var(--bg-code);
        border-color: var(--border-color-light);
      }
      
      .data-button:hover {
        background-color: var(--color-primary-light);
      }
      
      .overlay-data {
        background-color: var(--bg-code);
        color: var(--text-main);
      }
      
      .overlay-close:hover {
        background-color: var(--bg-button-hover);
      }
      
      /* Improve contrast for code blocks in dark mode */
      code {
        background-color: var(--bg-code);
        color: var(--text-main);
      }
      
      /* Make test status colors more visible in dark mode */
      .test-card.pass {
        background-color: rgba(46, 204, 113, 0.1);
      }
      
      .test-card.warning {
        background-color: rgba(243, 156, 18, 0.1);
      }
      
      .test-card.fail {
        background-color: rgba(231, 76, 60, 0.1);
      }
      
      /* Style links in dark mode */
      a, .test-link {
        color: var(--color-primary-light);
      }
      
      /* Fix the title border in dark mode */
      h1 {
        border-bottom-color: var(--color-primary);
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>azul-layout reftest results</h1>
      <!-- Header information -->
      <div class="report-header">
        <div class="header-metadata">
            <div class="metadata-item">
                <strong>CURRENT_TIME (rev <a href="https://github.com/fschutt/azul/commit/GIT_HASH"><code>GIT_HASH</code></a>)</strong>
                <p>tested against <strong class="metadata-item CHROME_CLASS">CHROME_VERSION</strong></p>
            </div>
        </div>
        
        <div class="project-info">
            <div class="links">
                <a href="https://docs.rs/azul-layout" target="_blank">Documentation</a> |
                <a href="https://azul.rs" target="_blank">Website</a> |
                <a href="https://github.com/fschutt/azul" target="_blank">GitHub</a> |
                <a href="https://crates.io/crates/azul-layout" target="_blank">crates.io</a>
            </div>
        </div>
    </div>
    
    <div class="summary">
      <div class="summary-box total">
        <div class="summary-number" id="totalTests">0</div>
        <div class="summary-label">Total Tests</div>
      </div>
      <div class="summary-box passed">
        <div class="summary-number" id="passedTests">0</div>
        <div class="summary-label">Passed (<span id="passPercentage">0</span>%)</div>
      </div>
      <div class="summary-box failed">
        <div class="summary-number" id="failedTests">0</div>
        <div class="summary-label">Failed (<span id="failPercentage">0</span>%)</div>
      </div>
      <div class="summary-box warning">
        <div class="summary-number" id="warningTests">0</div>
        <div class="summary-label">Warning (<span id="warnPercentage">0</span>%)</div>
      </div>
    </div>
    
    <div class="controls">
      <div class="search-controls">
        <input type="text" id="searchInput" class="search-input" placeholder="Search tests (e.g., 'grid', 'status:failing', 'status:passing')">
      </div>
      
      <div class="sort-controls">
        <button class="button sort-button active" data-sort="name">Sort by Name</button>
        <button class="button sort-button" data-sort="status">Sort by Status</button>
        <button class="button sort-button" data-sort="diff">Sort by Diff Count</button>
      </div>
      
      <div class="filter-controls">
        <button class="button filter-button active" data-filter="all">All Tests</button>
        <button class="button filter-button pass" data-filter="pass">Passed</button>
        <button class="button filter-button warning" data-filter="warning">Warning</button>
        <button class="button filter-button fail" data-filter="fail">Failed</button>
      </div>
    </div>
    
    <div class="test-grid" id="testGrid">
      <!-- Tests will be inserted here dynamically -->
    </div>
    
    <div class="no-results" id="noResults">
      <h3>No tests match the current filter</h3>
      <p>Try changing the filter criteria</p>
    </div>
  </div>
  
  <!-- Overlay for showing data -->
  <div class="overlay" id="dataOverlay">
    <div class="overlay-content">
      <div class="overlay-header">
        <h2 class="overlay-title" id="overlayTitle">Data Title</h2>
        <div class="overlay-close" onclick="closeOverlay()">&times;</div>
      </div>
      <div class="overlay-data" id="overlayData"></div>
    </div>
  </div>
  
  <script>
    // Test data in JSON format
    const testData = JSON.parse(atob("{TEST_DATA_BASE64}"));
    
    // DOM elements
    const testGrid = document.getElementById('testGrid');
    const noResults = document.getElementById('noResults');
    const totalTestsEl = document.getElementById('totalTests');
    const passedTestsEl = document.getElementById('passedTests');
    const failedTestsEl = document.getElementById('failedTests');
    const warningTestsEl = document.getElementById('warningTests');
    const passPercentageEl = document.getElementById('passPercentage');
    const failPercentageEl = document.getElementById('failPercentage');
    const warnPercentageEl = document.getElementById('warnPercentage');
    
    // Current filter and sort
    let currentFilter = 'all';
    let currentSort = 'name';
    let currentSearch = '';
    let groupedTests = {};
    
    // Initialize the page
    function initialize() {
      // Update summary
      updateSummary();
      
      // Group tests by category
      groupTestsByCategory();
      
      // Create test cards
      createTestCards();
      
      // Sort initially
      sortTestCards('name');
      
      // Setup event listeners
      setupEventListeners();
    }
    
    // Update summary statistics
    function updateSummary() {
      const totalTests = testData.length;
      const passedTests = testData.filter(test => test.passed).length;
      
      // Calculate warning tests (passed is false but diff_count is small)
      const totalPixels = 800 * 600; // Approximate based on default dimensions
      const warningTests = testData.filter(test => 
        !test.passed && test.diff_count <= totalPixels * 0.02
      ).length;
      
      const failedTests = totalTests - passedTests - warningTests;
      
      const passPercentage = totalTests > 0 ? Math.round((passedTests / totalTests) * 100) : 0;
      const failPercentage = totalTests > 0 ? Math.round((failedTests / totalTests) * 100) : 0;
      const warnPercentage = totalTests > 0 ? Math.round((warningTests / totalTests) * 100) : 0;
      
      totalTestsEl.textContent = totalTests;
      passedTestsEl.textContent = passedTests;
      failedTestsEl.textContent = failedTests;
      warningTestsEl.textContent = warningTests;
      passPercentageEl.textContent = passPercentage;
      failPercentageEl.textContent = failPercentage;
      warnPercentageEl.textContent = warnPercentage;
    }
    
    // Group tests by category and subcategory
    function groupTestsByCategory() {
      groupedTests = {};
      
      testData.forEach(test => {
        // Extract category from test name (assumes format like "category-subcategory-test")
        const parts = test.test_name.split('-');
        const category = parts.length > 2 ? parts[0] : 'uncategorized';
        const subcategory = parts.length > 2 ? parts[1] : parts[0];
        
        if (!groupedTests[category]) {
          groupedTests[category] = {};
        }
        if (!groupedTests[category][subcategory]) {
          groupedTests[category][subcategory] = [];
        }
        groupedTests[category][subcategory].push(test);
      });
    }
    
    // Check if test matches search query (supports status: filter)
    function testMatchesSearch(test, searchQuery) {
      if (!searchQuery) return true;
      
      const query = searchQuery.toLowerCase();
      
      // Handle status: filter
      if (query.startsWith('status:')) {
        const status = query.substring(7);
        const totalPixels = 800 * 600;
        
        if (status === 'passing' && test.passed) return true;
        if (status === 'failing' && !test.passed && test.diff_count > totalPixels * 0.02) return true;
        if (status === 'warning' && !test.passed && test.diff_count <= totalPixels * 0.02) return true;
        
        return false;
      }
      
      // Regular text search
      return test.test_name.toLowerCase().includes(query) || 
             (test.title && test.title.toLowerCase().includes(query)) ||
             (test.assert_content && test.assert_content.toLowerCase().includes(query));
    }
    
    // Create test cards
    function createTestCards() {
      testGrid.innerHTML = '';
      
      if (testData.length === 0) {
        testGrid.innerHTML = `
          <div class="empty-state">
            <div class="empty-icon">📝</div>
            <h3>No tests found</h3>
            <p>Run some tests to see results here</p>
          </div>
        `;
        return;
      }
      
      // Sort categories: showcase first, then alphabetically
      const categories = Object.keys(groupedTests).sort((a, b) => {
        if (a === 'showcase') return -1;
        if (b === 'showcase') return 1;
        return a.localeCompare(b);
      });
      
      categories.forEach(category => {
        const subcategories = Object.keys(groupedTests[category]).sort();
        
        subcategories.forEach(subcategory => {
          const tests = groupedTests[category][subcategory];
          const categoryTitle = category === subcategory ? category : `${category} / ${subcategory}`;
          
          // Create category header
          const categoryHeader = document.createElement('div');
          categoryHeader.className = 'category-header';
          categoryHeader.textContent = `${categoryTitle} (${tests.length} tests)`;
          testGrid.appendChild(categoryHeader);
          
          tests.forEach(test => {
            const card = createTestCard(test, category);
            testGrid.appendChild(card);
          });
        });
      });
    }
    
    // Create individual test card
    function createTestCard(test, category) {
      // Determine status class
      const totalPixels = 800 * 600;
      let statusClass = 'pass';
      let statusValue = 1;
      let resultText = 'PASS';
      
      if (!test.passed) {
        if (test.diff_count <= totalPixels * 0.02) {
          statusClass = 'warning';
          statusValue = 2;
          resultText = 'WARNING';
        } else {
          statusClass = 'fail';
          statusValue = 3;
          resultText = 'FAIL';
        }
      }
      
      const card = document.createElement('div');
      // Only expand showcase by default
      const isCollapsed = category !== 'showcase';
      card.className = `test-card ${statusClass}${isCollapsed ? ' collapsed' : ''}`;
      card.dataset.name = test.test_name;
      card.dataset.status = statusValue;
      card.dataset.diff = test.diff_count;
      card.dataset.filter = statusClass;
      card.dataset.category = category;
      
      card.innerHTML = `
        <div class="test-header" onclick="toggleTestCard(this)">
          <div class="test-header-left">
            <span class="collapse-icon">▼</span>
            <h3 class="test-title">${test.test_name}</h3>
          </div>
          <span class="test-result ${statusClass}">${resultText} // ${test.diff_count} px diff</span>
        </div>
        
        <div class="test-body">
          <div class="test-metadata">
            <div class="test-title-full">${escapeHtml(test.title || test.test_name)}</div>
            ${test.assert_content ? `<div class="test-assert">${escapeHtml(test.assert_content)}</div>` : ''}
            ${test.help_link ? `<a href="${escapeHtml(test.help_link)}" target="_blank" class="test-link">Specification Reference</a>` : ''}
          </div>
          
          <div class="test-content">
            <div class="test-image-container">
              <img class="test-image lazy" data-src="./reftest_img/${test.test_name}_chrome.webp" alt="Chrome Reference">
              <div class="test-image-label">Chrome Reference</div>
            </div>
            
            <div class="test-image-container">
              <img class="test-image lazy" data-src="./reftest_img/${test.test_name}_azul.webp" alt="Azul Rendering">
              <div class="test-image-label">Azul Rendering</div>
            </div>
          </div>
          
          <div class="test-data-buttons">
            <button class="data-button" data-test="${test.test_name}" data-type="xhtml">View XHTML</button>
            <button class="data-button" data-test="${test.test_name}" data-type="warnings">CSS Warnings</button>
            <button class="data-button" data-test="${test.test_name}" data-type="xml">Parsed XML</button>
            <button class="data-button" data-test="${test.test_name}" data-type="dom">Styled DOM</button>
            <button class="data-button" data-test="${test.test_name}" data-type="layout">Solved Layout</button>
            <button class="data-button" data-test="${test.test_name}" data-type="display">Display List</button>
            <button class="data-button" data-test="${test.test_name}" data-type="copy" onclick="copyDebugData('${test.test_name}')">Copy Debug</button>
          </div>
        </div>
      `;
      
      return card;
    }
    
    // Toggle test card collapse state
    function toggleTestCard(headerEl) {
      const card = headerEl.closest('.test-card');
      card.classList.toggle('collapsed');
      
      // Load images if not already loaded and card is expanded
      if (!card.classList.contains('collapsed')) {
        loadLazyImages(card);
      }
    }
    
    // Load lazy images for a card
    function loadLazyImages(card) {
      const lazyImages = card.querySelectorAll('img.lazy');
      lazyImages.forEach(img => {
        if (img.dataset.src && !img.src) {
          img.src = img.dataset.src;
          img.classList.remove('lazy');
        }
      });
    }
    
    // Setup event listeners
    function setupEventListeners() {
      // Search input
      const searchInput = document.getElementById('searchInput');
      searchInput.addEventListener('input', (e) => {
        currentSearch = e.target.value;
        filterTestCards(currentFilter, currentSearch);
      });
      
      // Sort buttons
      document.querySelectorAll('.sort-button').forEach(button => {
        button.addEventListener('click', () => {
          document.querySelectorAll('.sort-button').forEach(b => b.classList.remove('active'));
          button.classList.add('active');
          
          currentSort = button.dataset.sort;
          sortTestCards(currentSort);
        });
      });
      
      // Filter buttons
      document.querySelectorAll('.filter-button').forEach(button => {
        button.addEventListener('click', () => {
          document.querySelectorAll('.filter-button').forEach(b => b.classList.remove('active'));
          button.classList.add('active');
          
          currentFilter = button.dataset.filter;
          filterTestCards(currentFilter, currentSearch);
        });
      });
      
      // Data buttons
      document.querySelectorAll('.data-button').forEach(button => {
        button.addEventListener('click', () => {
          const testName = button.dataset.test;
          const dataType = button.dataset.type;
          showDataOverlay(testName, dataType);
        });
      });
    }
    
    // Sort test cards
    function sortTestCards(sortBy) {
      // Sorting is now handled by grouping, so we just recreate the cards
      createTestCards();
      filterTestCards(currentFilter, currentSearch);
    }
    
    // Filter test cards
    function filterTestCards(filter, searchQuery = '') {
      const cards = Array.from(testGrid.querySelectorAll('.test-card'));
      const categoryHeaders = Array.from(testGrid.querySelectorAll('.category-header'));
      let visibleCount = 0;
      
      // Track which categories have visible tests
      const visibleCategories = new Set();
      
      cards.forEach(card => {
        const test = testData.find(t => t.test_name === card.dataset.name);
        const matchesFilter = filter === 'all' || card.dataset.filter === filter;
        const matchesSearch = testMatchesSearch(test, searchQuery);
        
        if (matchesFilter && matchesSearch) {
          card.style.display = '';
          visibleCount++;
          visibleCategories.add(card.dataset.category);
        } else {
          card.style.display = 'none';
        }
      });
      
      // Show/hide category headers based on visible tests
      categoryHeaders.forEach(header => {
        const categoryName = header.textContent.split(' (')[0];
        const hasVisibleTests = Array.from(visibleCategories).some(cat => 
          categoryName.includes(cat) || categoryName.includes('/')
        );
        header.style.display = hasVisibleTests ? '' : 'none';
      });
      
      // Show "no results" message if needed
      if (visibleCount === 0 && cards.length > 0) {
        noResults.style.display = 'block';
      } else {
        noResults.style.display = 'none';
      }
    }
    
    // Show data overlay
    function showDataOverlay(testName, dataType) {
      const overlay = document.getElementById('dataOverlay');
      const overlayTitle = document.getElementById('overlayTitle');
      const overlayData = document.getElementById('overlayData');
      
      // Find the test data
      const test = testData.find(t => t.test_name === testName);
      
      if (!test) {
        console.error(`Test not found: ${testName}`);
        return;
      }
      
      // Set title and data based on type
      let title;
      let data;
      
      switch (dataType) {
        case 'xhtml':
          title = 'XHTML Source';
          data = test.xhtml_source || 'XHTML source not available.';
          break;
        case 'warnings':
          title = 'CSS Warnings';
          data = test.css_warnings || 'No CSS warnings.';
          break;
        case 'xml':
          title = 'Parsed XML';
          data = test.parsed_xml || 'Parsed XML not available.';
          break;
        case 'dom':
          title = 'Styled DOM';
          data = test.styled_dom || 'Styled DOM not available.';
          break;
        case 'layout':
          title = 'Solved Layout';
          data = test.solved_layout || 'Solved layout not available.';
          break;
        case 'display':
          title = 'Display List';
          data = test.display_list || 'Display list not available.';
          break;
        case 'copy':
          // Handled by onclick handler
          return;
        default:
          title = 'Unknown Data Type';
          data = 'Data not available.';
      }
      
      overlayTitle.textContent = `${title} - ${testName}`;
      overlayData.textContent = data;
      
      // Show the overlay
      overlay.style.display = 'block';
      
      // Disable scrolling on the body
      document.body.style.overflow = 'hidden';
    }
    
    // Close the overlay
    function closeOverlay() {
      const overlay = document.getElementById('dataOverlay');
      overlay.style.display = 'none';
      
      // Restore scrolling on the body
      document.body.style.overflow = 'auto';
    }
    
    // Helper: Escape HTML
    function escapeHtml(unsafe) {
      if (!unsafe) return '';
      return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
    }
    
    // Copy all debug data to clipboard
    function copyDebugData(testName) {
      // Find the test data
      const test = testData.find(t => t.test_name === testName);
      if (!test) {
        console.error(`Test not found: ${testName}`);
        return;
      }
      
      // Concatenate all debug data
      const allData = [
        "=== XHTML SOURCE ===",
        test.xhtml_source || "Not available",
        "\n=== CSS WARNINGS ===",
        test.css_warnings || "No CSS warnings",
        "\n=== PARSED XML ===",
        test.parsed_xml || "Not available",
        "\n=== STYLED DOM ===",
        test.styled_dom || "Not available",
        "\n=== SOLVED LAYOUT ===",
        test.solved_layout || "Not available",
        "\n=== DISPLAY LIST ===",
        test.display_list || "Not available",
        "\n=== RENDER DEBUG MSGS ===",
        test.render_warnings || "Not available"
      ].join("\n");
      
      // Copy to clipboard
      navigator.clipboard.writeText(allData)
        .then(() => {
          alert("Debug data copied to clipboard!");
        })
        .catch(err => {
          console.error("Could not copy text: ", err);
          alert("Failed to copy debug data. See console for details.");
        });
    }
    
    // Close overlay when clicking outside the content
    document.getElementById('dataOverlay').addEventListener('click', (e) => {
      if (e.target === document.getElementById('dataOverlay')) {
        closeOverlay();
      }
    });
    
    // Close overlay with escape key
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') {
        closeOverlay();
      }
    });
    
    // Initialize on load
    document.addEventListener('DOMContentLoaded', initialize);
  </script>
</body>
</html>